<?php
App::uses('CakeEmail', 'Network/Email');

/**
 * CakePHP BroadcastShell
 * @author Francis Adu-Gyamfi <francis.adu-gyamfi@matrixdesigns.org>
 */
class BroadcastShell extends AppShell {

    public $uses = array('ModuleSmsAccount', 'ModuleSmsAccountBroadcast', 'ModuleSmsBroadcastList', 'OrganisationNotification');
    public $tasks = array('Sms');

    public function main() {
        ini_set('max_execution_time', '120');
        
        $this->out("Starting SMS Broadcast Processing");
        
        $response = $this->processBroadcasts();
        
        if( $response['status'] == 'success' && $response['code'] == 'SP001' ) {
            $this->out('Processed Broadcast ID ' . $response['broadcast_list_id'] . ". Sending email notification to organisation.");
            $this->sendProcessCompleteNotification( $response['account_id'], $response['list'] );
        }
        
        $this->out('Ending Broadcast Processing');
    }
    
    public function findUnsentBroadcast() {
        return $this->ModuleSmsAccountBroadcast->find('first', array(
            'conditions' => array(
                'ModuleSmsAccountBroadcast.sent' => 0,
                'ModuleSmsAccountBroadcast.send_at <' => date('Y-m-d H:i:s'),
                'ModuleSmsAccountBroadcast.active' => 1
            ),
            'order' => array('ModuleSmsAccountBroadcast.send_at')
        ));
    }

    public function processBroadcasts() {
        $broadcast = $this->findUnsentBroadcast();
        
        if( $broadcast ) {
            $send_limit = 100;
            
            $organisation_id = $broadcast['ModuleSmsAccount']['organisation_id'];
            $account_id = $broadcast['ModuleSmsAccountBroadcast']['module_sms_account_id'];
            $broadcast_list_id = $broadcast['ModuleSmsAccountBroadcast']['module_sms_broadcast_list_id'];
            $broadcast_id = $broadcast['ModuleSmsAccountBroadcast']['id'];
            $broadcast_list_name = '';
            $send_offset = $broadcast['ModuleSmsAccountBroadcast']['sent_offset'];            
            $message = $broadcast['ModuleSmsAccountBroadcast']['message'];
            $sender_id = null;
            $category_id = $broadcast['ModuleSmsAccountBroadcast']['organisation_member_category_id'];
            
            $sms_account = $this->ModuleSmsAccount->getAccount($organisation_id);
            
            if( !$sms_account ) {
                return array('status' => 'failed', 'error_type' => 'no_account', 'message' => 'An SMS Messaging Account is not active for the specified organisation');
            }
            
            // temp data
            $contacts_data = array('contacts' => array());
            
            if( $broadcast_list_id ) { 
                $sender_id = $broadcast['ModuleSmsBroadcastList']['sender_id'];
                $broadcast_list_name = $broadcast['ModuleSmsBroadcastList']['name'];
                
                $contacts_data = $this->ModuleSmsBroadcastList->buildList($account_id, $broadcast_list_id, $send_limit, $send_offset);

                if( $contacts_data['status'] == 'failed' ) {
                    return $contacts_data;
                }
            }
            
            else if( $category_id ) {
                $contacts_data = $this->ModuleSmsBroadcastList->buildPredefinedList($account_id, $category_id, $send_limit, $send_offset);

                if( $contacts_data['status'] == 'failed' ) {
                    return $contacts_data;
                } else {
                    $broadcast_list_name = $contacts_data['list']['name'];
                }
            }
            
            // get the list of contacts to send
            $contacts = $contacts_data['contacts'];
            
            if( !$sender_id ) {
                $sender_id = $sms_account['ModuleSmsAccount']['sender_id'];
            }
            
            if( $sms_account['ModuleSmsAccount']['account_balance'] < count($contacts_data) ) {
                $this->OrganisationNotification->add($organisation_id, 'sms_broadcast_low_credit', array(
                    'source_id' => $account_id,
                    'target_id' => $broadcast_list_id,
                    'broadcast_list_name' => $broadcast_list_name
                ));
                
                return array('status' => 'failed', 'error_type' => 'no_credit', 'message' => $message);
            }
            
            $time = new DateTime();
            $errors = array();
            $sent_count = 0;
            
            foreach ($contacts as $contact) {
                $time->add(new DateInterval("PT5S"));

                $response = $this->Sms->send($contact['number'], $message, $sender_id);
                
                if ( isset($response['error']) ) {
                    $errors[] = $response['error'];
                }
                
                else if( $response['status'] === 'error' ) {
                    $errors[] = $response;
                }
                
                else {
                    $sent_count++;
                }
                
                $send_offset++;
            }
            
            if ($sent_count) {
                $this->ModuleSmsAccount->deductCredit($organisation_id, $sent_count);
            }
            
            // record the
            $this->ModuleSmsAccountBroadcast->updateSendCounters($broadcast_id, $send_limit, $sent_count);

            if (count($errors) > 0) {
                return array('status' => 'warning', 'code' => 'SP003', 'message' => 'Messages were sent with errors', 'errors' => $errors);
            }
            
            // if all messages have been processed
            if( $send_offset >= $contacts_data['list']['size'] && $sent_count > 0 ) {
                $broadcast_list_name = $contacts_data['list']['name'];
                $list_size = $contacts_data['list']['size'];
                $logMessage = "<b>$sent_count</b> of <b>$list_size</b> messages for <b>$broadcast_list_name</b> processed successfully.";
                
                $this->ModuleSmsAccountBroadcast->setProcessed($broadcast_id, 1);
                $this->OrganisationNotification->add($organisation_id, 'sms_broadcast_processing_complete', array(
                    'source_id' => $account_id,
                    'target_id' => $broadcast_list_id,
                    'broadcast_list_name' => $broadcast_list_name
                ));
                
                return array(
                    'status' => 'success',
                    'code' => 'SP001',
                    'message' => $logMessage,
                    'account_id' => $account_id,
                    'broadcast_list_id' => $broadcast_list_id,
                    'account_balance' => $this->ModuleSmsAccount->getAccountBalance($organisation_id),
                    'list' => $contacts_data['list']
                );
            }

            // some messages have been processed but more remain
            else if( $send_offset < $contacts_data['list']['size'] && $sent_count > 0 ) {
                return array(
                    'status' => 'success',
                    'code' => 'SP002',
                    'message' => "Processed $send_offset Of {$contacts_data['list']['size']} at " . date('Y-m-d H:i:s'),
                    'broadcast_list_id' => $broadcast_list_id,
                    'list' => $contacts_data['list']
                );
            }
            
            return array(
                'status' => 'failed',
                'code' => 'SP005',
                'message' => 'No messages were sent',
                'log_dt' => date('Y-m-d H:i:s')
            );
        }
        
        return array(
            'status' => 'failed',
            'code' => 'SP004',
            'message' => 'No available broadcasts to be processed',
            'log_dt' => date('Y-m-d H:i:s')
        );
    }
    
    public function sendProcessCompleteNotification($account_id, $list) {
        $account = $this->ModuleSmsAccount->getAccountById($account_id);
        
        if($account) {
            $email = new CakeEmail('smtp');
            $email->domain("memberz.org");
            $email->from(array('support@memberz.org' => 'Memberz Support'));
            $email->to( array($account['Organisation']['email'], 'support@memberz.org') );
            $email->subject('SMS Broadcast Processing Complete');
            $email->send('Processing of SMS Broadcast List ' . $list['name'] . " Completed.");
            $this->out('OK');
        }
    }
}
